/*
New Scotland Yard is an online multiplayer adaptation
of the boardgame "Scotland Yard". Copyright (C) 2011
Massey University Software C Group 3
This program is free software: you can redistribute it
and/or modify it under the terms of the GNU General
Public License as published by the Free Software
Foundation, either version 3 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General
Public License along with this program. If not, see
<http://www.gnu.org/licenses/>.
*/
package nz.ac.massey.softwarec.group3.login;
import java.io.IOException;
import java.net.InetAddress;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.openid4java.OpenIDException;
import org.openid4java.consumer.ConsumerManager;
import org.openid4java.consumer.InMemoryConsumerAssociationStore;
import org.openid4java.consumer.InMemoryNonceVerifier;
import org.openid4java.consumer.VerificationResult;
import org.openid4java.discovery.DiscoveryException;
import org.openid4java.discovery.DiscoveryInformation;
import org.openid4java.discovery.Identifier;
import org.openid4java.message.AuthRequest;
import org.openid4java.message.AuthSuccess;
import org.openid4java.message.ParameterList;
import org.openid4java.message.ax.AxMessage;
import org.openid4java.message.ax.FetchRequest;
import org.openid4java.message.ax.FetchResponse;
import org.openid4java.util.HttpClientFactory;
import org.openid4java.util.ProxyProperties;
/**
* OpenId4Java - Handles the OpenID authentication.
* @version 1.0 Release
* @since 1.0
* @authors Natalie Eustace | Wanting Huang | Paul Smith | Craig Spence
*/
@WebServlet(name = "OpenId4Java", urlPatterns = {"/openid"})
public class OpenId4Java extends HttpServlet {
private static ConsumerManager consumerManager;
final static String YAHOO_ENDPOINT = "https://me.yahoo.com";
final static String GOOGLE_ENDPOINT = "https://www.google.com/accounts/o8/id";
final static String REDIRECT_LOCATION = "/Software_Engineering_C/Resources/JavaServerPages/lobby.jsp";
private static ConsumerManager getConsumerManager() {
try {
// Proxy stuff, comment out when not at Massey.
InetAddress myLocalHost = InetAddress.getLocalHost();
//If have a 10 prefixed ip comment out this block of code if not at massey
if(myLocalHost.getHostAddress().startsWith("10")){
final ProxyProperties proxyProps = new ProxyProperties();
proxyProps.setProxyHostName("tur-cache2.massey.ac.nz");
proxyProps.setProxyPort(8080);
proxyProps.setUserName("08497818");
proxyProps.setPassword("6891");
HttpClientFactory.setProxyProperties(proxyProps);
}
} catch (IOException ex) {
System.err.print(ex.getMessage());
}
try {
if (consumerManager == null) {
consumerManager = new ConsumerManager();
consumerManager.setAssociations(new InMemoryConsumerAssociationStore());
consumerManager.setNonceVerifier(new InMemoryNonceVerifier(10000));
}
} catch (Exception ex) {
final String message = "Exception creating ConsumerManager!";
throw new RuntimeException(message, ex);
}
return consumerManager;
}
public static DiscoveryInformation performDiscoveryOnUserSuppliedIdentifier(final String userSuppliedIdentifier) {
DiscoveryInformation ret = null;
consumerManager = getConsumerManager();
try {
// Perform discover on the User-Supplied Identifier
final List<DiscoveryInformation> discoveries =
consumerManager.discover(userSuppliedIdentifier);
// Pass the discoveries to the associate() method...
ret = consumerManager.associate(discoveries);
} catch (DiscoveryException de) {
final String message = "Error occurred during discovery!";
throw new RuntimeException(message, de);
}
return ret;
}
public static AuthRequest createOpenIdAuthRequest(final DiscoveryInformation discoveryInformation, final String returnToUrl, final String endpoint) {
AuthRequest ret = null;
//
try {
// Create the AuthRequest object
ret = getConsumerManager().authenticate(discoveryInformation, returnToUrl);
final FetchRequest fetch = FetchRequest.createFetchRequest();
if (endpoint.startsWith(GOOGLE_ENDPOINT)) {
fetch.addAttribute("email", "http://axschema.org/contact/email", true);
fetch.addAttribute("FirstName", "http://axschema.org/namePerson/first", true);
fetch.addAttribute("LastName", "http://axschema.org/namePerson/last", true);
} else if (endpoint.startsWith(YAHOO_ENDPOINT)) {
fetch.addAttribute("email", "http://axschema.org/contact/email", true);
fetch.addAttribute("Fullname", "http://axschema.org/namePerson", true);
}
ret.addExtension(fetch);
} catch (Exception e) {
final String message = "Exception occurred while building "
+ "AuthRequest object!";
throw new RuntimeException(message, e);
}
return ret;
}
private Identifier verifyResponse(final HttpServletRequest request) {
try {
// extract the parameters from the authentication response
// (which comes in as a HTTP request from the OpenID provider)
final ParameterList response = new ParameterList(request.getParameterMap());
// retrieve the previously stored discovery information
final DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute("openid-disc");
// extract the receiving URL from the HTTP request
final StringBuffer receivingURL = request.getRequestURL();
final String queryString = request.getQueryString();
if (queryString != null && queryString.length() > 0) {
receivingURL.append("?").append(request.getQueryString());
}
// verify the response; ConsumerManager needs to be the same
// (static) instance used to place the authentication request
final VerificationResult verification = consumerManager.verify(receivingURL.toString(), response, discovered);
// examine the verification result and extract the verified
// identifier
final Identifier verified = verification.getVerifiedId();
if (verified != null) {
final AuthSuccess authSuccess = (AuthSuccess) verification.getAuthResponse();
if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
final FetchResponse fetchResp = (FetchResponse) authSuccess.getExtension(AxMessage.OPENID_NS_AX);
final String email = fetchResp.getAttributeValue("email");
final String lastname = fetchResp.getAttributeValue("LastName");
final String firstname = fetchResp.getAttributeValue("FirstName");
final String fullname = fetchResp.getAttributeValue("fullname");
final HttpSession session = request.getSession();
if (fullname == null) {
session.setAttribute("username", firstname + " " + lastname);
}
else {
session.setAttribute("username", fullname);
}
session.setAttribute("email", email);
}
return verified; // success
}
} catch (OpenIDException ex) {
System.err.print(ex);
}
return null;
}
/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
final Identifier identifier = this.verifyResponse(request);
response.sendRedirect(REDIRECT_LOCATION);
}
/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
final String url = request.getParameter("openid");
final DiscoveryInformation discoveryInformation = performDiscoveryOnUserSuppliedIdentifier(url);
final InetAddress myLocalHost = InetAddress.getLocalHost();
final AuthRequest authRequest = createOpenIdAuthRequest(discoveryInformation, "http://" + myLocalHost.getHostAddress() + ":8080/Software_Engineering_C/openid", url);
response.sendRedirect(authRequest.getDestinationUrl(true));
}
/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "This servlet allows user authentication with OpenId";
}
}